Ext.ux.IpV4Field = Ext.extend(Ext.form.Field, {
	defaultAutoCreate : {tag: 'div', 'class' : 'ipv4-field-wrap'},
	IpV4FieldTpl : new Ext.XTemplate(
	'<div class="ipv4-field-input1" style="display: inline; float: left; width: 30px;"></div>',
	'<div class="ipv4-field-input1-spacer" style="position: relative;"><div style="position:absolute;bottom:0; left: 3px;">.</div></div>',
	'<div class="ipv4-field-input2" style="display: inline; float: left; width: 30px;"></div>',
	'<div class="ipv4-field-input2-spacer" style="position: relative;"><div style="position:absolute;bottom:0; left: 3px;">.</div></div>',
	'<div class="ipv4-field-input3" style="display: inline; float: left; width: 30px;"></div>',
	'<div class="ipv4-field-input3-spacer" style="position: relative;"><div style="position:absolute;bottom:0; left: 3px;">.</div></div>',
	'<div class="ipv4-field-input4"  style="display: inline; float: left; width: 30px;"></div>',
	'<div class="ipv4-field-hidden"></div>'
	),

	initComponent: function(){
		Ext.ux.IpV4Field.superclass.initComponent.call(this);
	},

	reset : function() {
		this.clearValue();
		this.setValue(this.value);
	},

	setValue : function(v) {

		if(this.is_numeric(v)) v = this.long2ip(v);

		if (v == undefined || v == null)
			return;

		ip_arr = v.split('.', 4);

		if(ip_arr.length == 4) {
			if(this.input1) this.input1.setValue(ip_arr[0]);
			if(this.input2) this.input2.setValue(ip_arr[1]);
			if(this.input3) this.input3.setValue(ip_arr[2]);
			if(this.input4) this.input4.setValue(ip_arr[3]);
		}

		if(this.hiddenField) this.hiddenField.setValue(v);
	},

	markInvalid : function(msg) {
		Ext.ux.IpV4Field.superclass.markInvalid.call(this);

		if(this.input1) this.input1.markInvalid(msg);
		if(this.input2) this.input2.markInvalid(msg);
		if(this.input3) this.input3.markInvalid(msg);
		if(this.input4) this.input4.markInvalid(msg);
	},

	clearInvalid : function() {
		Ext.ux.IpV4Field.superclass.clearInvalid.call(this);

		if(this.input1) this.input1.clearInvalid();
		if(this.input2) this.input2.clearInvalid();
		if(this.input3) this.input3.clearInvalid();
		if(this.input4) this.input4.clearInvalid();
	},

	clearValue : function() {
		if(this.input1) this.input1.setValue();
		if(this.input2) this.input2.setValue();
		if(this.input3) this.input3.setValue();
		if(this.input4) this.input4.setValue();
	},

	getValue: function()
	{
		if(this.hiddenField) return this.hiddenField.getValue();
		else return '';
	},

	// private

	onDisable: function(){
		Ext.ux.IpV4Field.superclass.onDisable.call(this);
		this.doDisable(true);
	},

	onEnable: function(){
		Ext.ux.IpV4Field.superclass.onEnable.call(this);
		this.doDisable(false);

	},

	// private
	doDisable: function(disabled){
		if(this.input1) this.input1.setDisabled(disabled);
		if(this.input2) this.input2.setDisabled(disabled);
		if(this.input3) this.input3.setDisabled(disabled);
		if(this.input4) this.input4.setDisabled(disabled);
	},

	setRealValue: function() {
		var rt = '';

		if(this.input1) rt += this.input1.getValue() + '.';
		if(this.input2) rt += this.input2.getValue() + '.';
		if(this.input3) rt += this.input3.getValue() + '.';
		if(this.input4) rt += this.input4.getValue();

		if(this.IPAsLong) {
			rt = this.ip2long(rt);
		}

		if(this.hiddenField) this.hiddenField.setValue(rt);
	},

	createInput: function(idx) {
		this['input' + idx + 'Ct'] = Ext.query('.ipv4-field-input' + idx, this.el.dom)[0];
		this['input' + idx]   = Ext.create({
			xtype: 'numberfield',
			maxLength: 3,
			allowDecimals : false,
			allowNegative: false,
			minValue: 0,
			maxValue: 255,
			hideLabel: true,
			width: 30,
			renderTo : this['input' + idx + 'Ct'],
			allowBlank: this.allowBlank ? true : false,
			disabled: this.disabled ? true : false,
			autoCreate: {tag: "input", type: "text", size: 3, autocomplete: "off", maxlength: 3, style: "float: left"},
			parentComponent: this,
			listeners: {
				change: function() {
					this.parentComponent.setRealValue();
				}
			}
		});

		this['input' + idx].getEl().dom.removeAttribute('name');
	},

	onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
		Ext.ux.IpV4Field.superclass.onResize.call(this, adjWidth, adjHeight, rawWidth, rawHeight);
	},

	onRender : function(ct, position) {
		var i = 0;

		Ext.ux.IpV4Field.superclass.onRender.call(this, ct, position);
		this.el.update(this.IpV4FieldTpl.apply(this));

		for(i = 1; i < 5; i++)
		{
			this.createInput(i);
		}

		this['hiddenCt']      = Ext.query('.ipv4-field-hidden', this.el.dom)[0];
		this['hiddenField']   = Ext.create({
			xtype: 'hidden',
			name: this.name,
			renderTo : this['hiddenCt']
		});


	},

	ip2long: function (IP) {
		// Converts a string containing an (IPv4) Internet Protocol dotted address into a proper address
		//
		// version: 1008.1718
		// discuss at: http://phpjs.org/functions/ip2long    // +   original by: Waldo Malqui Silva
		// +   improved by: Victor
		// +    revised by: fearphage (http://http/my.opera.com/fearphage/)
		// +    revised by: Theriault
		// *     example 1: ip2long('192.0.34.166');    // *     returns 1: 3221234342
		// *     example 2: ip2long('0.0xABCDEF');
		// *     returns 2: 11259375
		// *     example 3: ip2long('255.255.255.256');
		// *     returns 3: false    var i = 0;
		// PHP allows decimal, octal, and hexadecimal IP components.
		// PHP allows between 1 (e.g. 127) to 4 (e.g 127.0.0.1) components.
		IP = IP.match(/^([1-9]\d*|0[0-7]*|0x[\da-f]+)(?:\.([1-9]\d*|0[0-7]*|0x[\da-f]+))?(?:\.([1-9]\d*|0[0-7]*|0x[\da-f]+))?(?:\.([1-9]\d*|0[0-7]*|0x[\da-f]+))?$/i); // Verify IP format.
		if (!IP) {        return false; // Invalid format.
		}
		// Reuse IP variable for component counter.
		IP[0] = 0;
		for (i = 1; i < 5; i += 1) {        IP[0] += !!((IP[i] || '').length);
		IP[i] = parseInt(IP[i]) || 0;
		}
		// Continue to use IP for overflow values.
		// PHP does not allow any component to overflow.    IP.push(256, 256, 256, 256);
		// Recalculate overflow of last component supplied to make up for missing components.
		IP[4 + IP[0]] *= Math.pow(256, 4 - IP[0]);
		if (IP[1] >= IP[5] || IP[2] >= IP[6] || IP[3] >= IP[7] || IP[4] >= IP[8]) {
			return false;    }
			return IP[1] * (IP[0] === 1 || 16777216) + IP[2] * (IP[0] <= 2 || 65536) + IP[3] * (IP[0] <= 3 || 256) + IP[4] * 1;
	},

	long2ip: function ( proper_address ) {
		// Converts an (IPv4) Internet network address into a string in Internet standard dotted format
		//
		// version: 1008.1718
		// discuss at: http://phpjs.org/functions/long2ip    // +   original by: Waldo Malqui Silva
		// *     example 1: long2ip( 3221234342 );
		// *     returns 1: '192.0.34.166'

		var output = false;
		if ( !isNaN( proper_address ) && ( proper_address >= 0 || proper_address <= 4294967295 ) ) {
			output = Math.floor(proper_address / Math.pow( 256, 3 ) ) + '.' +
			Math.floor( ( proper_address % Math.pow( 256, 3 ) ) / Math.pow( 256, 2 ) ) + '.' +
			Math.floor( ( ( proper_address % Math.pow( 256, 3 ) )  % Math.pow( 256, 2 ) ) / Math.pow( 256, 1 ) ) + '.' +            Math.floor( ( ( ( proper_address % Math.pow( 256, 3 ) ) % Math.pow( 256, 2 ) ) % Math.pow( 256, 1 ) ) / Math.pow( 256, 0 ) );
		}

		return output;
	},

	is_numeric: function(mixed_var) {
		// Returns true if value is a number or a numeric string
		//
		// version: 1008.1718
		// discuss at: http://phpjs.org/functions/is_numeric    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// +   improved by: David
		// +   improved by: taith
		// +   bugfixed by: Tim de Koning
		// +   bugfixed by: WebDevHobo (http://webdevhobo.blogspot.com/)    // +   bugfixed by: Brett Zamir (http://brett-zamir.me)
		// *     example 1: is_numeric(186.31);
		// *     returns 1: true
		// *     example 2: is_numeric('Kevin van Zonneveld');
		// *     returns 2: false    // *     example 3: is_numeric('+186.31e2');
		// *     returns 3: true
		// *     example 4: is_numeric('');
		// *     returns 4: false
		// *     example 4: is_numeric([]);    // *     returns 4: false
		return (typeof(mixed_var) === 'number' || typeof(mixed_var) === 'string') && mixed_var !== '' && !isNaN(mixed_var);
	}

});

Ext.reg('ipv4field', Ext.ux.IpV4Field);
